package com.erdos.common.service;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.erdos.common.dao.DaoBase;
import com.erdos.common.entity.AbstractEntity;
import com.erdos.common.pagination.Page;


public class BaseCRUDService<T extends AbstractEntity> implements
		BaseService<T> {

	private static final long serialVersionUID = 1L;

	protected final Log logger = LogFactory.getLog(this.getClass());

	// model's Class
	protected Class<T> entityClass;

	// model's ClassName
	protected String entityClassName;

	private DaoBase<T> baseDao;

	@SuppressWarnings("unchecked")
	public BaseCRUDService() {
		try {
			Object genericClz = getClass().getGenericSuperclass();
			if (genericClz instanceof ParameterizedType) {
				entityClass = (Class<T>) ((ParameterizedType) getClass()
						.getGenericSuperclass()).getActualTypeArguments()[0];
				entityClassName = entityClass.getSimpleName();
			}
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	private DaoBase<T> getBaseDao() {
		DaoBase<T> baseDao = null;
		if (this.entityClass != null) {
			baseDao = (DaoBase<T>) AppServiceHelper.findBean(StringUtils
					.uncapitalize(entityClassName)
					+ "Dao");
		} else {
			baseDao = this.baseDao;
		}
		// logger.debug("baseDao=" + baseDao);
		return baseDao;
	}

	public int delete(T entity) {
		return getBaseDao().delete(entity);
	}

	public int deleteByPrimaryKey(Long sid) {
		return getBaseDao().deleteByPrimaryKey(sid);
	}

	public void deleteAll(Collection<T> collection) {
		getBaseDao().deleteAll(collection);
	}

	public void deleteAllByPrimaryKey(final Collection<Long> sids) {
		getBaseDao().deleteAllByPrimaryKey(sids);
	}

	public List<T> findAll() {
		return getBaseDao().findAll();
	}

	public List<T> findByParams(Map<String, Object> params) {
		return getBaseDao().findByParams(params);
	}

	public T findByPrimaryKey(Long id) {
		return getBaseDao().findByPrimaryKey(id);
	}

	public List<T> findByPrimaryKeys(Long[] ids) {
		return getBaseDao().findByPrimaryKeys(ids);
	}

	public T findUniqueByParams(Map<String, Object> params) {
		return getBaseDao().findUniqueByParams(params);
	}

	public Long insert(T entity) {
		return getBaseDao().insert(entity);
	}

	public void insertAll(Collection<T> collection) {
		getBaseDao().insertAll(collection);
	}

	public void update(T entity) {
		getBaseDao().update(entity);
	}

	public void updateAll(Collection<T> collection) {
		getBaseDao().updateAll(collection);
	}

	public Page<T> findByPage(Map<String, Object> params, int pageNo, int limit) {
		Date start, end;
		start = new Date();
		Page<T> page = getBaseDao().findByPage(params, pageNo, limit);
		end = new Date();
		logger.debug("findByPage from service cost time="
				+ (end.getTime() - start.getTime()));
		return page;
	}

	public Object findObjectBySqlID(String sqlID, Map<String, Object> params) {
		return getBaseDao().findObjectBySqlID(sqlID, params);
	}

	@SuppressWarnings("unchecked")
	public List findListBySqlID(String sqlID, Map<String, Object> params) {
		return getBaseDao().findListBySqlID(sqlID, params);
	}

	public void insertHistory(Map<String, Object> params) {
		getBaseDao().insertHistory(params);
	}

	public void setBaseDao(DaoBase<T> baseDao) {
		this.baseDao = baseDao;
	}
}
